package com.wanjia.bpsapi.controller;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wanjia.bpsapi.annotation.LoginToken;
import com.wanjia.bpsapi.constant.CalType;
import com.wanjia.bpsapi.exception.ControllerException;
import com.wanjia.bpsapi.pojo.dto.*;
import com.wanjia.bpsapi.pojo.entity.BaseClient;
import com.wanjia.bpsapi.pojo.entity.WjStoreProduct;
import com.wanjia.bpsapi.pojo.model.JsonResult;
import com.wanjia.bpsapi.properties.CalculateProperties;
import com.wanjia.bpsapi.service.*;
import com.wanjia.bpsapi.util.JsonResultUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

import static com.wanjia.bpsapi.constant.Constant.BIG_DECIMAL_SCALE;


@RestController
@Slf4j
@Tag(name = "报价计算接口控制器")
public class OfferController extends BaseController {


    @Autowired
    IDistanceService distanceService;

    @Autowired
    IParamService iParamService;

    @Autowired
    IWjStoreProductService iWjStoreProductService;

    @Autowired
    IWjSupplierService iWjSupplierService;

    @Autowired
    IWjUserService iWjUserService;

    @Autowired
    IMapService mapService;

    @Setter(onMethod_ = @Autowired)
    private IBaseClientService baseClientService;

    @Setter(onMethod_ = @Autowired)
    private IPutClientService putClientService;

    @Setter(onMethod_ = @Autowired)
    private CalculateProperties properties;

    @PostMapping("/offer")
    @Operation(summary = "报价计算接口")
    @Parameter(name = "token", in = ParameterIn.HEADER)
    @LoginToken
    @Transactional(isolation= Isolation.SERIALIZABLE)
    public JsonResult offerData(Long vegeId, Long uid, Long[] paramIds) {
        Arrays.sort(paramIds);
        WjStoreProduct storeNames = iWjStoreProductService.getById(vegeId);
        String keyword = storeNames.getKeyword();
        List<VegePrice> priceList;
        if (StrUtil.isNotEmpty(keyword)){
            priceList = iWjStoreProductService.getOtherPrice(vegeId, uid);
            log.info("基地对应报价以及距离:{}", priceList);
        } else {
            String storeName = storeNames.getStoreName();
            priceList = iWjStoreProductService.getPrice(storeName, uid);//获取商品规格单价
            log.info("基地对应报价以及距离:{}", priceList);
        }
        List<ParamNeed> list1 = iParamService.getList(paramIds, vegeId);
        log.info("参数项和转换系数:{}", list1);
        boolean containYuanPerOne = list1.stream()
                .anyMatch(pn -> Objects.equals(pn.getCaltype(), CalType.YUAN_PRE_ONE.code()));

        QueryWrapper wrapper =new QueryWrapper();
        wrapper.eq("vege_id",vegeId);
        wrapper.eq("client_id",uid);
        wrapper.eq("cost",Arrays.toString(paramIds));
        boolean remove = baseClientService.remove(wrapper);
        log.info("是否删除重复数据:{}", remove);

        for (VegePrice vegePrice : priceList) {
            BigDecimal price = vegePrice.getPrice();
            BigDecimal prices = containYuanPerOne ? price : price.multiply(BigDecimal.valueOf(1000));
            double distance = vegePrice.getDistance();
            for (ParamNeed paramNeed : list1) {
                BigDecimal conversion = paramNeed.getConversion();
                if (conversion == null) {
                    throw new ControllerException(paramNeed.getConsumable() + "的转换系数不能为空");
                }
                if (paramNeed.getCaltype() == CalType.COMMON.code()) {
                    prices = prices.add(paramNeed.getPrice().multiply(conversion));
                    log.info("{} * {} = {}", paramNeed.getPrice(), conversion, paramNeed.getPrice().multiply(conversion));
                }
                if (paramNeed.getCaltype() == CalType.DISTANCE.code()) {
                    prices = prices.add(paramNeed.getPrice()
                            .multiply(conversion)
                            .multiply(BigDecimal.valueOf(distance))
                            .divide(BigDecimal.valueOf(properties.getDistanceConversion()), BIG_DECIMAL_SCALE, RoundingMode.HALF_UP)
                    );
                    log.info("{} * {} * {}  = {}", paramNeed.getPrice(), conversion, distance,
                            paramNeed.getPrice().multiply(conversion).multiply(BigDecimal.valueOf(distance)));
                }
                if (paramNeed.getCaltype() == CalType.YUAN_PER_CATTY.code()) {
                    prices = prices.add(conversion.multiply(BigDecimal.valueOf(2000)));
                    log.info("{} * 2000 = {}",  conversion,
                            conversion.multiply(BigDecimal.valueOf(2000)));
                }
                if (paramNeed.getCaltype() == CalType.ONE_PRE_CATTY.code()) {
                    prices = prices.add(paramNeed.getPrice()
                            .multiply(BigDecimal.valueOf(2000))
                            .divide(conversion, BIG_DECIMAL_SCALE, RoundingMode.HALF_UP));
                    log.info("2000 * {} / {} = {}", paramNeed.getPrice(),  conversion,
                            paramNeed.getPrice()
                                    .multiply(BigDecimal.valueOf(2000))
                                    .divide(conversion, BIG_DECIMAL_SCALE, RoundingMode.HALF_UP));
                }
                if (paramNeed.getCaltype() == CalType.YUAN_PRE_ONE.code()) {
                    prices = prices.add(paramNeed.getPrice());
                    log.info("{}", paramNeed.getPrice());
                }
            }
            log.info("价格：{}", prices);
            String cost = Arrays.toString(paramIds);
            BaseClient baseClient = new BaseClient();
            baseClient.setBaseId(vegePrice.getBaseId());
            baseClient.setClientId(vegePrice.getClientId());
            baseClient.setVegeId((long) vegeId);
            baseClient.setCost(cost);
            baseClient.setOffer(prices);
            Integer id = vegePrice.getId();
            long RealVegeid=(long) id;
            baseClient.setRealVegeid(RealVegeid);
            baseClient.setWjProductOfferId(vegePrice.getWjProductOfferId());
            baseClientService.insertOffer(baseClient);
        }

        return new JsonResult(OK);
    }

    @PostMapping("/offer/list")
    @Operation(summary = "报价计算结果查询接口")
    @Parameter(name = "token", in = ParameterIn.HEADER)
    @LoginToken
    public JsonResult<List<BaseClientOffer>> getOffers(@RequestBody GetOffers go) {
        return JsonResultUtil.success(baseClientService.getOffers(go));
    }

    @PostMapping("/offer/putaway")
    @Operation(summary = "上架接口")
    @Parameter(name = "token", in = ParameterIn.HEADER)
    @LoginToken
    public JsonResult<Void> putAway(@RequestBody PutAwayData data) {
        baseClientService.putAway(data);
        return JsonResultUtil.success();
    }

    @GetMapping("/offer/putaway")
    @Operation(summary = "获取上架记录接口")
    @Parameter(name = "token", in = ParameterIn.HEADER)
    @LoginToken
    public JsonResult<Page<PutAwayDTO>> getPutAwayList(
            @Parameter(description = "页码") Integer pageNo,
            @Parameter(description = "页尺寸") Integer pageSize,
            @Parameter(description = "菜品id") @RequestParam(required = false) Long vegeId,
            @Parameter(description = "客户id") @RequestParam(required = false) Long clientId,
            @Parameter(description = "上架时间-起") @RequestParam(required = false) Long startPutDate,
            @Parameter(description = "上架时间-终") @RequestParam(required = false) Long endPutDate
    ) {
        return JsonResultUtil.success(putClientService.pagePutAway(pageNo - 1, pageSize, vegeId, clientId,
                Optional.ofNullable(startPutDate).map(Date::new).orElse(null),
                Optional.ofNullable(endPutDate).map(Date::new).orElse(null)));
    }
}
